home *** CD-ROM | disk | FTP | other *** search
- /*
- * fsDisk.c --
- *
- * Routines related to managing local disks. Each partition of a local
- * disk (partitions are defined by a table on the disk header) is
- * called a ``domain''. FsAttachDisk attaches a domain into the file
- * system, and FsDeattachDisk removes it. A domain is given
- * a number the first time it is ever attached. This is recorded on
- * the disk so it doesn't change between boots. The domain number is
- * used to identify disks, and a domain number plus a file number is
- * used to identify files. Fsdm_DomainFetch is used to get the state
- * associated with a disk, and Fsdm_DomainRelease releases the reference
- * on the state. FsDetachDisk checks the references on domains in
- * the normal (non-forced) case so that active disks aren't detached.
- *
- * Copyright 1987 Regents of the University of California
- * All rights reserved.
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifdef notdef
- static char rcsid[] = "$Header: /sprite/src/boot/decprom/RCS/fsDisk.c,v 1.1 90/02/16 16:14:11 shirriff Exp Locker: shirriff $ SPRITE (Berkeley)";
- #endif not lint
-
-
- #include "sprite.h"
-
- #include "fsBoot.h"
- #include "kernel/devDiskLabel.h"
- #include "kernel/dev.h"
- #include "kernel/devFsOpTable.h"
- #include "kernel/machMon.h"
- /*
- * fsDevice is copied into all Fsio_FileIOHandles. It is used by the drivers
- * to get to the partition and geometry information for the disk.
- */
- Fs_Device fsDevice;
-
- /*
- * fsDomainPtr and fsRootHandlePtr are used by Fs_Open.
- */
- static Fsdm_Domain fsDomain;
- Fsdm_Domain *fsDomainPtr = &fsDomain;
- static Fsio_FileIOHandle fsRootHandle;
- Fsio_FileIOHandle *fsRootHandlePtr = &fsRootHandle;
-
- /*
- * Forward declarations.
- */
- static int InstallLocalDomain();
- void AddDomainFlags();
- static Boolean IsDecLabel();
-
- /*
- *----------------------------------------------------------------------
- *
- * FsAttachDisk --
- *
- * Make a particular local disk partition correspond to a prefix.
- * This makes sure the disk is up, reads the domain header,
- * and calls the initialization routine for the block I/O module
- * of the disk's driver. By the time this is called the device
- * initialization routines have already been called from Dev_Config
- * so the device driver knows how the disk is partitioned into
- * domains. This routine sees if the domain is formatted correctly,
- * and if so attaches it to the set of domains.
- *
- * Results:
- * SUCCESS if the disk was readable and had a good domain header.
- *
- * Side effects:
- * Sets up the Fsdm_DomainInfo for the domain.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- FsAttachDisk(fsDevicePtr)
- Fs_Device *fsDevicePtr; /* Global FS device descriptor */
- {
- ReturnStatus status; /* Error code */
- register Address buffer; /* Read buffer */
- int headerSector; /* Starting sector of domain header */
- int numHeaderSectors; /* Number of sectors in domain header */
- int summarySector; /* Sector of summary information. */
- Fsdm_SummaryInfo *summaryInfoPtr; /* Pointer to summary info. */
- int amountRead; /* Returned from read call */
- int devType; /* Device type index */
-
- /*
- * Open the raw disk device so we can grub around in the header info.
- */
- Mach_MonPrintf("FsAttachDisk: ptr = %x\n", fsDevicePtr);
- devType = DEV_TYPE_INDEX(fsDevicePtr->type);
- status = (*devFsOpTable[devType].open)(&fsDevice);
- if (status != SUCCESS) {
- Mach_MonPrintf("Failure\n");
- return(status);
- }
- Mach_MonPrintf("Mallocing\n");
- buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
- Mach_MonPrintf("Done mallocing\n");
-
- /*
- * Read the 31st sector of the partition. It has a copy of the
- * 31st sector of the whole disk which describes how the rest of the
- * domain's zero'th cylinder is layed out.
- */
- status = (*devFsOpTable[devType].read)(&fsDevice,
- DEC_LABEL_SECTOR*DEV_BYTES_PER_SECTOR,
- DEV_BYTES_PER_SECTOR, buffer, &amountRead);
- if (status != SUCCESS) {
- #ifndef NO_PRINTF
- Mach_MonPrintf("label (sector 31) read fail\n");
- #endif
- return(status);
- }
- Mach_MonPrintf("Checking format\n");
- /*
- * Check for different disk formats, and figure out how the rest
- * of the zero'th cylinder is layed out.
- */
- if (((Dec_DiskLabel *)buffer)->magic != DEC_LABEL_MAGIC) {
- #ifndef NO_PRINTF
- Mach_MonPrintf("Bad magic <%x>\n", ((Dec_DiskLabel *)buffer)->magic);
- #endif
- }
-
- headerSector = ((Dec_DiskLabel *)buffer)->domainSector;
- numHeaderSectors = ((Dec_DiskLabel *)buffer)->numDomainSectors;
- /*
- * Read the domain header and save it with the domain state.
- */
- buffer = (Address)malloc(DEV_BYTES_PER_SECTOR * numHeaderSectors);
- status = (*devFsOpTable[devType].read)(&fsDevice,
- headerSector * DEV_BYTES_PER_SECTOR,
- numHeaderSectors * DEV_BYTES_PER_SECTOR,
- buffer, &amountRead);
- Mach_MonPrintf("Read header\n");
- if (status != SUCCESS) {
- #ifndef NO_PRINTF
- Mach_MonPrintf("Domain fail\n");
- #endif
- return(status);
- } else if (((Fsdm_DomainHeader *)buffer)->magic != FSDM_DOMAIN_MAGIC) {
- #ifndef NO_PRINTF
- Mach_MonPrintf("Bad magic <%x>\n",
- ((Fsdm_DomainHeader *)buffer)->magic);
- #endif
- return(FAILURE);
- }
-
- fsDomainPtr->headerPtr = (Fsdm_DomainHeader *) buffer;
-
- /*
- * Set up the ClientData part of *devicePtr to reference the
- * Fsdm_Geometry part of the domain header. This is used by the
- * block I/O routines.
- */
- fsDevicePtr->data = (ClientData)&fsDomainPtr->headerPtr->geometry;
-
- /*
- * Set up a file handle for the root directory. What is important
- * is the device info (for Block IO) and the file descriptor itself.
- */
- Mach_MonPrintf("Init'ing handle\n");
- FsInitFileHandle(fsDomainPtr, FSDM_ROOT_FILE_NUMBER, fsRootHandlePtr);
- Mach_MonPrintf("Done\n");
- return(SUCCESS);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * IsSunLabel --
- *
- * Poke around in the input buffer and see if it looks like
- * a Sun format disk label.
- *
- * Results:
- * TRUE or FALSE
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- #ifdef notdef
- static Boolean
- IsSunLabel(buffer)
- Address buffer; /* Buffer containing zero'th sector */
- {
- register Sun_DiskLabel *sunLabelPtr;
-
- sunLabelPtr = (Sun_DiskLabel *)buffer;
- if (sunLabelPtr->magic == SUN_DISK_MAGIC) {
- /*
- * Should check checkSum...
- */
- return(TRUE);
- } else {
- return(FALSE);
- }
- }
- #endif
-
- /*
- *----------------------------------------------------------------------
- *
- * IsSpriteLabel --
- *
- * Poke around in the input buffer and see if it looks like
- * a Sprite format disk header.
- *
- * Results:
- * TRUE or FALSE
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- #ifdef notdef
- static Boolean
- IsSpriteLabel(buffer)
- Address buffer; /* Buffer containing zero'th sector */
- {
- register FsDiskHeader *diskHeaderPtr;
- register int index;
- register int checkSum;
-
- diskHeaderPtr = (FsDiskHeader *)buffer;
- if (diskHeaderPtr->magic == FSDM_DISK_MAGIC) {
- return(TRUE);
- }
- }
- return(FALSE);
- }
- #endif
-
- /*
- *----------------------------------------------------------------------
- * The following routines are used by device drivers to map from block
- * and sector numbers to disk addresses. There are two sets, one for
- * drivers that use logical sector numbers (i.e. SCSI) and the other
- * for <cyl,head,sector> format disk addresses.
- *----------------------------------------------------------------------
- */
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_BlocksToSectors --
- *
- * Convert from block indexes (actually, fragment indexes) to
- * sectors using the geometry information on the disk. This
- * is a utility for block device drivers.
- *
- * Results:
- * The sector number that corresponds to the fragment index.
- * The caller has to make sure that its I/O doesn't cross a
- * filesystem block boundary.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- #define SECTORS_PER_FRAG (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
- #if defined(SCSI_DISK_BOOT) || defined(SUN_PROM_BOOT)
- int
- Fs_BlocksToSectors(fragNumber, data)
- int fragNumber; /* Fragment index to map into block index */
- ClientData data; /* ClientData from the device info */
- {
- register Fsdm_Geometry *geoPtr;
- register int sectorNumber; /* The sector corresponding to the fragment */
- register int cylinder; /* The cylinder number of the fragment */
- register int rotationalSet; /* The rotational set with cylinder of frag */
- register int blockNumber; /* The block number within rotational set */
-
- geoPtr = (Fsdm_Geometry *)data;
- blockNumber = fragNumber / FS_FRAGMENTS_PER_BLOCK;
- cylinder = blockNumber / geoPtr->blocksPerCylinder;
- if (geoPtr->rotSetsPerCyl > 0) {
- /*
- * Do fancy rotational set mapping.
- */
- blockNumber -= cylinder * geoPtr->blocksPerCylinder;
- rotationalSet = blockNumber / geoPtr->blocksPerRotSet;
- blockNumber -= rotationalSet * geoPtr->blocksPerRotSet;
-
- sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
- geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
- rotationalSet +
- geoPtr->blockOffset[blockNumber];
- sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
- } else {
- /*
- * Do straight-forward mapping.
- */
- sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
- fragNumber * SECTORS_PER_FRAG - cylinder *
- geoPtr->blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK *
- SECTORS_PER_FRAG;
- }
-
- return(sectorNumber);
- }
- #endif
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_BlocksToDiskAddr --
- *
- * Convert from block indexes (actually, fragment indexes) to
- * disk address (head, cylinder, sector) using the geometry information
- * on the disk. This is a utility for block device drivers.
- *
- * Results:
- * The disk address that corresponds to the disk address.
- * The caller has to make sure that its I/O doesn't cross a
- * filesystem block boundary.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- #ifdef XYLOGICS_BOOT
- void
- Fs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
- int fragNumber; /* Fragment index to map into block index */
- ClientData data; /* ClientData from the device info */
- Dev_DiskAddr *diskAddrPtr;
- {
- register Fsdm_Geometry *geoPtr;
- register int sectorNumber; /* The sector corresponding to the fragment */
- register int cylinder; /* The cylinder number of the fragment */
- register int rotationalSet; /* The rotational set with cylinder of frag */
- register int blockNumber; /* The block number within rotational set */
-
- geoPtr = (Fsdm_Geometry *)data;
- /*
- * Map to block number because the rotational sets are laid out
- * relative to blocks. After that the cylinder is easy because we know
- * blocksPerCylinder. To get the head and sector we first get the
- * rotational set (described in fsDisk.h) of the block and the
- * block's sector offset (relative to the rotational set!). This complex
- * algorithm crops up because there isn't necessarily an even number
- * of blocks per track. The 'blockOffset' array in the geometry gives
- * a sector index of each successive block in a rotational set. Finally,
- * we can use the sectorsPerTrack to get the head and sector.
- */
- blockNumber = fragNumber / FS_FRAGMENTS_PER_BLOCK;
- cylinder = blockNumber / geoPtr->blocksPerCylinder;
- blockNumber -= cylinder * geoPtr->blocksPerCylinder;
- diskAddrPtr->cylinder = cylinder;
-
- rotationalSet = blockNumber / geoPtr->blocksPerRotSet;
- blockNumber -= rotationalSet * geoPtr->blocksPerRotSet;
- /*
- * The follow statment had to be broken into two because the compiler used
- * register d2 to do the modulo operation, but wasn't saving its value.
- */
- sectorNumber = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
- rotationalSet + geoPtr->blockOffset[blockNumber];
- sectorNumber +=
- (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
-
- diskAddrPtr->head = sectorNumber / geoPtr->sectorsPerTrack;
- diskAddrPtr->sector = sectorNumber -
- diskAddrPtr->head * geoPtr->sectorsPerTrack;
- }
- #endif
-
- /*
- *----------------------------------------------------------------------
- *
- * Fs_SectorsToRawDiskAddr --
- *
- * Convert from a sector offset to a raw disk address (cyl, head,
- * sector) using the geometry information on the disk. This is a
- * utility for raw device drivers and does not pay attention to the
- * rotational position of filesystem disk blocks.
- *
- * This should be moved to Dev
- *
- * Results:
- * The disk address that corresponds exactly to the byte offset.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
- #ifdef XYLOGICS_BOOT
- int
- Fs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
- int sector; /* Sector number (counting from zero 'til the total
- * number of sectors in the disk) */
- int numSectors; /* Number of sectors per track */
- int numHeads; /* Number of heads on the disk */
- Dev_DiskAddr *diskAddrPtr;
- {
- register int sectorsPerCyl; /* The rotational set with cylinder of frag */
-
- sectorsPerCyl = numSectors * numHeads;
- diskAddrPtr->cylinder = sector / sectorsPerCyl;
- sector -= diskAddrPtr->cylinder * sectorsPerCyl;
- diskAddrPtr->head = sector / numSectors;
- diskAddrPtr->sector = sector - numSectors * diskAddrPtr->head;
- }
- #endif
-
-
- /*
- *----------------------------------------------------------------------
- *
- * FsDeviceBlockIO --
- *
- * Map a file system block address to a block device block address
- * perform the requested operation.
- *
- * NOTE: This routine is temporary and should be replaced when the file system
- * is converted to use the async block io interface.
- *
- * Results:
- * The return status of the operation.
- *
- * Side effects:
- * Blocks may be written or read.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- FsDeviceBlockIO(readWriteFlag, devicePtr, fragNumber, numFrags, buffer)
- int readWriteFlag; /* FS_READ or FS_WRITE */
- Fs_Device *devicePtr; /* Specifies device type to do I/O with */
- int fragNumber; /* CAREFUL, fragment index, not block index.
- * This is relative to start of device. */
- int numFrags; /* CAREFUL, number of fragments, not blocks */
- Address buffer; /* I/O buffer */
- {
- ReturnStatus status; /* General return code */
- int firstSector; /* Starting sector of transfer */
- DevBlockDeviceRequest request;
- int transferCount;
- int devType;
-
- devType = DEV_TYPE_INDEX(devicePtr->type);
- if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
- /*
- * The I/O doesn't start on a block boundary. Transfer the
- * first few extra fragments to get things going on a block boundary.
- */
- register int extraFrags;
-
- extraFrags = FS_FRAGMENTS_PER_BLOCK -
- (fragNumber % FS_FRAGMENTS_PER_BLOCK);
- if (extraFrags > numFrags) {
- extraFrags = numFrags;
- }
- firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
- status = (*devFsOpTable[devType].read)(devicePtr,
- firstSector * DEV_BYTES_PER_SECTOR,
- extraFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
- if (status != SUCCESS) {
- #ifndef NO_PRINTF
- Mach_MonPrintf("Fragment read failure\n");
- #endif
- }
- extraFrags = transferCount / FS_FRAGMENT_SIZE;
- fragNumber += extraFrags;
- buffer += transferCount;
- numFrags -= extraFrags;
- }
- if (numFrags > 0) {
- /*
- * Transfer the left over fragments.
- */
- firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
- status = (*devFsOpTable[devType].read)(devicePtr,
- firstSector * DEV_BYTES_PER_SECTOR,
- numFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
- if (status != SUCCESS) {
- #ifndef NO_PRINTF
- Mach_MonPrintf("Last fragment read failure\n");
- #endif
- }
- }
- return(status);
- }
-
-